package com.example.service.message.mq;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.example.common.constant.Constants;
import com.example.common.enums.command.MessageCommand;
import com.example.common.model.message.MessageContent;
import com.example.common.model.message.MessageReadedContent;
import com.example.common.model.message.MessageReciveAckContent;
import com.example.common.model.message.RecallMessageContent;
import com.example.service.message.service.MessageStoreService;
import com.example.service.message.service.MessageSyncService;
import com.example.service.message.service.P2PMessageService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.rabbitmq.client.Channel;

import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.Objects;

//用户接收mq发送的消息
@Component
public class ChatOperateReceiver {


    @Autowired
    P2PMessageService p2PMessageService;


    @Autowired
    MessageSyncService messageSyncService;


    private static Logger logger = LoggerFactory.getLogger(ChatOperateReceiver.class);


    @RabbitListener(
            bindings = @QueueBinding(
                    value = @Queue(value = Constants.RabbitConstants.Im2MessageService,durable = "true"),
                    exchange = @Exchange(value =Constants.RabbitConstants.Im2MessageService ,durable = "true")
            ),concurrency = "10"
    )
    public void onChatMessage(@Payload Message message,
                              @Headers Map<String,Object> headers,
                              Channel channel) throws Exception {
        String msg = new String(message.getBody(),"utf-8");
        logger.info("CHAT MSG FORM QUEUE ::: {}", msg);
        Long deliveryTag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG);
        try{
            JSONObject jsonObject=JSON.parseObject(msg);
            Integer command=jsonObject.getInteger("command");
            if(command.equals(MessageCommand.MSG_P2P.getCommand())){   //表示是单聊
                // 处理消息
                MessageContent messageContent=jsonObject.toJavaObject(MessageContent.class);
                //这边可以对消息进行进一步的处理 比如鉴黄  这里可以将消息进行存到 消息队列中 如果发现消息有问题可以调用一个撤回的方法
                p2PMessageService.process(messageContent);           //单聊消息的验证处理
            } else if (command.equals(MessageCommand.MSG_RECIVE_ACK.getCommand())) {
                //对消息确认接收的确认包
                MessageReciveAckContent messageContent=jsonObject.toJavaObject(MessageReciveAckContent.class);
                messageSyncService.receiveMark(messageContent);     //进行消息接收确认
            }else if (command.equals(MessageCommand.MSG_READED.getCommand())){   //表示进行了消息已读
                MessageReadedContent messageReadedContent= jsonObject.toJavaObject(MessageReadedContent.class);
                messageSyncService.readMark(messageReadedContent);
            } else if (Objects.equals(command, MessageCommand.MSG_RECALL.getCommand())){
                //                撤回消息
                RecallMessageContent messageContent = JSON.parseObject(msg, new TypeReference<RecallMessageContent>() {
                }.getType());
                messageSyncService.recallMessage(messageContent);
            }
            channel.basicAck(deliveryTag, false);
        }catch (Exception e){
            logger.error("处理消息出现异常：{}", e.getMessage());
            logger.error("RMQ_CHAT_TRAN_ERROR", e);
            logger.error("NACK_MSG:{}", msg);
            //第一个false 表示不批量拒绝，第二个false表示不重回队列
            channel.basicNack(deliveryTag, false, false);
        }

    }

}
